/*******************************************************************\
*	file: 		XCMDUtils.c											*
*	version:	1.05§												*
* 																	*
* Support routines for the Appletalk/Hypercard interface.			*
* -----------------------------------------------------------------	*
* By:	Greg Kimberly, Donald Koscheka								*
* Date:	21-Sept-87													*
* ©	Copyright 1987, Apple Computer, Inc.							*
*	All Rights Reserved												*
*																	*
* -----------------------------------------------------------------	*
*						Modification History						*
* -----------------------------------------------------------------	*
*  Date	   	| By	|	 				Description					*
* -----------------------------------------------------------------	*
* 21-Sep-87	| GK	| file created									*
*  5-Nov-87	| DK	| changed ErrorReturn to return a handle to an	*
*			| 		| an error string rather than report the error	*
*			|		| deliteralized default error number			*
* 11-Dec-87	| DK	| changed save and retrieve handle to use longs	*
* 14-Jan-88	| DK	| Retrieve and savehandles to pass the id of the*
*			|		| resource to access.							*
*  1-Feb-88	| DK	| Return empty rather than "No Error" if no 	*
*			| 		| error (a la James Redfern).					*
* 10-Feb-88	| DK	| changed Savehandle to set handle to empty	if 	*
*			|		| it receives a nil handle (rather than save 0)	*
* 22-Feb-88 | DK	| Move all locked handles high					*
* -----------------------------------------------------------------	*
\*******************************************************************/

#include	<Types.h>
#include 	<AppleTalk.h>
#include	<Resources.h>
#include 	<OSUtils.h>
#include	<Packages.h>
#include	<Memory.h>
#include	"atalkxcmd.h"
#include	"xcmdutils.h"
#include 	"HyperXCmd.h"


#define isUpper( c ) ( (c >= 'A' && c <= 'Z') ? 1 : 0 )
#define isLower( c ) ( (c >= 'a' && c <= 'z') ? 1 : 0 )
#define	toUpper( c ) ( (isLower( c )) ? c - 'a' + 'A': c )
#define toLower( c ) ( (isUpper( c )) ? c + 'a' - 'A': c )


void SaveHandle(paramPtr, theID, theHandle)
	XCmdBlockPtr	paramPtr;
	short			theID;
	long 			theHandle;
/**********************************
* Save a handle away in the Hypercard
* global heap.  The name of the global 
* variable to use is stored in the 
* resource file.  Extract that name,
* get a handle to the data and do the
* dirty deed.
*
* In:	theID = resource id of the container
*		theHandle = thehandle or pointer to save away
*
**********************************/
{
	Handle 	name, DataHandle;
	char 	buffHandle[256];

	name = GetResource('STR ', theID );			/*get name of global*/
	*buffHandle = '\0';
	
	if( theHandle )
		LongToStr( paramPtr, theHandle, buffHandle );
		
	DataHandle = PasToZero(paramPtr, buffHandle);
	MoveHHi( name );
	HLock(name);
	SetGlobal(paramPtr, *name, DataHandle );	/* put it into HyperCard global name */
	DisposHandle( DataHandle );
	HUnlock( name );
}


long RetrieveHandle(paramPtr, theID)
	XCmdBlockPtr	paramPtr;
	short			theID;
/**********************************
* Retrieve a handle away from the Hypercard
* global heap.  The name of the global 
* variable to use is stored in the 
* resource file.  Extract that name,
* get a handle to the data and 
* return the data in that container.
* note that hypercard stores all of
* its data as null-strings, so we must
* convert it back to a handle...
*
* In:	theID = id of the handle or pointer
*				to retrieve.
*
**********************************/
{
	Handle		name;
	Handle		DataHandle;
	char		localString[256];
	long		returnHandle;
	
	name = GetResource('STR ', theID ); 		/* get name of global	*/
	MoveHHi( name );
	HLock(name);								/* lock name			*/
	DataHandle = GetGlobal(paramPtr,*name); 	/* get HyperCard global */
	HUnlock(name);		
	if ( DataHandle ){
		MoveHHi( DataHandle );
		HLock( DataHandle );
		ZeroToPas(paramPtr, *DataHandle, localString);
		returnHandle = StrToLong( paramPtr, localString );
		HUnlock( DataHandle );
		DisposHandle( DataHandle );
		return( (long)returnHandle );
	}
	else
		return( 0L );
}


Handle ErrorReturn( theErr )
	short theErr;
/**********************************
* Given a system error number in theErr
* extract its string from the resource
* fork and returns it to HyperCard
*
* If we can't work out the error string,
* build one using the error number.
**********************************/
{
	Handle	strhand = nil;
	char	s[256];
	char	num[256];
	long	len = 0;
	
	if(theErr == noErr)
		return( nil );

	*s = '\0';
	
	strhand = GetResource( 'STR ', theErr );
	if( strhand ){
		/*** copy the string to another handle and save it off ***/
		len = GetHandleSize( strhand );
		BlockMove( *strhand, s, len );
		p2cstr( s );
	}
	else{
		s[0]='E'; s[1]='R'; s[2]='R'; s[3]='O'; s[4]='R'; s[5]=' '; s[6]='\0';
		NumToString( (long)theErr, num );
		sappend( s, num );
		len = (long)slength( s );
	}
	
	if( *s ){
		strhand = NewHandle( len );
		BlockMove( s, *strhand, len );
	}
	return( strhand );
}



/*******************	 	Miscellaneous Support Routines		*******************/

void pStrCopy( inStr,outStr )
	unsigned char *inStr, *outStr;
/*********************************
* copy the pascal-style string from
* the input string to the output 
* string.
*********************************/
{
	short i;
	
	for (i = 0; i <= inStr[0]; i++)
		outStr[i] = inStr[i];
}


short slength( str )
	unsigned char	*str;
/*********************************
* return the length of a c string
* including the '\0' byte. 
*********************************/
{
	short i = 0;
	
	while( *str++ )
		i++;
		
	return( (i+1) );
}


short strcopy( dst, src )
	unsigned char	*dst, *src;
/*********************************
* Copy a "C" string to another
* "C" string. 
*********************************/
{
	while( *dst++ = *src++ );
}


short sappend( dst, src )
	unsigned char	 *dst, *src;
/*********************************
* NOTE: the destination
* string must be large enough to hold
* both strings going in!
*
* tacks source onto destination.
*********************************/
{
	while( *dst )
		dst++;
	while( *dst++ = *src++ );
}


short strCMP( s1, s2 )
	unsigned char	*s1, *s2;
/*********************************
* compare two c strings regardless
* of case returning:
*
* <0 if s1 < s2
* 0  if s1 == s2
* >0 if s1 > s2
*********************************/
{
	
	for( ; toUpper( *s1 ) == toUpper( *s2 ); s1++, s2++ )
		if( *s1 == '\0' )
			return( 0 );
			
	return( *s1 - *s2 );
}


MakeAnswer( bool, str )
	short	bool;
	char	*str;
/*********************
* create the returing string
* as "TRUE" or "FALSE"
*********************/
{
	if( bool ){
		*str++ = 'T';
		*str++ = 'R';
		*str++ = 'U';
		*str++ = 'E';
		*str++ = '\0';
	}
	else{
		*str++ = 'F';
		*str++ = 'A';
		*str++ = 'L';
		*str++ = 'S';
		*str++ = 'E';
		*str++ = '\0';
	}
}

/******************** C routines for HyperCard callbacks *************************/
#include "XCmdGlue.inc.c"
